
#include "misc.h"
#include "usb_keyboard.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_exti.h"
#include "usb_core.h"
#include "usb_pwr.h"
#include "usb_desc.h"
#include "delay.h"
#include "led.h"
#include "usb_regs.h"
extern __IO uint8_t PrevXferComplete;
extern __IO uint32_t bDeviceState;
uint32_t OLD_KEYDATA;
uint8_t USB_KEYBOARD_DATAS[9];
uint8_t USB_KEYBOARD_DATA=0x00;
__IO uint16_t KEYBOARD_COLUMN_GPIO_Pin[11] =
{
	COLUMN01_PIN,
	COLUMN02_PIN,
	COLUMN03_PIN,
	COLUMN04_PIN,
	COLUMN05_PIN,
	COLUMN06_PIN,
	COLUMN07_PIN,
	COLUMN08_PIN,
	COLUMN09_PIN,
	COLUMN10_PIN,
	COLUMN11_PIN
};
GPIO_TypeDef* KEYBOARD_COLUMN_GPIO_PORT[11] =
{
	COLUMN01_PORT,
	COLUMN02_PORT,
	COLUMN03_PORT,
	COLUMN04_PORT,
	COLUMN05_PORT,
	COLUMN06_PORT,
	COLUMN07_PORT,
	COLUMN08_PORT,
	COLUMN09_PORT,
	COLUMN10_PORT,
	COLUMN11_PORT
};
__IO uint16_t KEYBOARD_ROW_GPIO_Pin[11] =
{
	ROW01_PIN,
	ROW02_PIN,
	ROW03_PIN,
	ROW04_PIN,
	ROW05_PIN,
	ROW06_PIN,
	ROW07_PIN,
	ROW08_PIN,
	ROW09_PIN,
	ROW10_PIN,
	ROW11_PIN
};
GPIO_TypeDef* KEYBOARD_ROW_GPIO_PORT[11] =
{
	ROW01_PORT,
	ROW02_PORT,
	ROW03_PORT,
	ROW04_PORT,
	ROW05_PORT,
	ROW06_PORT,
	ROW07_PORT,
	ROW08_PORT,
	ROW09_PORT,
	ROW10_PORT,
	ROW11_PORT
};

/*******************************************************************************
* Function Name : EXTI_Configuration.
* Description   : Configure the EXTI lines for Key and Tamper push buttons.
* Input         : None.
* Output        : None.
* Return value  : The direction value.
*******************************************************************************/
void EXTI_Configuration(void)
{
	EXTI_InitTypeDef EXTI_InitStructure;
	
	EXTI_InitStructure.EXTI_Line = EXTI_Line13;
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
	EXTI_Init(&EXTI_InitStructure);

	/* Clear the Tamper EXTI line pending bit */
	EXTI_ClearITPendingBit(EXTI_Line13);

	/* Configure the EXTI line 18 connected internally to the USB IP */
	EXTI_ClearITPendingBit(EXTI_Line18);
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
	EXTI_InitStructure.EXTI_Line = EXTI_Line18;
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
	EXTI_Init(&EXTI_InitStructure);
}

/*******************************************************************************
* Function Name  : Set_System
* Description    : Configures Main system clocks & power.
* Input          : None.
* Return         : None.
*******************************************************************************/
void Set_System(void)
{
	EXTI_Configuration();
}

/*******************************************************************************
* Function Name  : USB_Interrupts_Config.
* Description    : Configures the USB interrupts.
* Input          : None.
* Output         : None.
* Return         : None.
*******************************************************************************/
void USB_Interrupts_Config(void)
{
	
	NVIC_InitTypeDef NVIC_InitStructure;
	/* 2 bit for pre-emption priority, 2 bits for subpriority */
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	/* Enable the USB_HP interrupt */
	NVIC_InitStructure.NVIC_IRQChannel = USB_HP_CAN1_TX_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);

	/* Enable the USB_LP interrupt */
	NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);

	/* Enable the USB Wake-up interrupt */
	NVIC_InitStructure.NVIC_IRQChannel = USBWakeUp_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);

	/* Enable the EXTI15_10 Interrupt */
	/* Enable SW-DP */
	NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
}


/*******************************************************************************
* Function Name  : Set_USBClock
* Description    : Configures USB Clock input (48MHz).
* Input          : None.
* Output         : None.
* Return         : None.
*******************************************************************************/
void Set_USBClock(void)
{
	RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_1Div5);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USB, ENABLE);
}

/*******************************************************************************
* Function Name  : Leave_LowPowerMode.
* Description    : Restores system clocks and power while exiting suspend mode.
* Input          : None.
* Output         : None.
* Return         : None.
*******************************************************************************/
void Leave_LowPowerMode(void)
{
	DEVICE_INFO *pInfo = &Device_Info;

	/* Set the device state to the correct state */
	if (pInfo->Current_Configuration != 0)
	{
		/* Device configured */
		bDeviceState = CONFIGURED;
	}
	else
	{
		bDeviceState = ATTACHED;
	}
	/*Enable SystemCoreClock*/
	SystemInit();
#if defined(STM32L1XX_MD) || defined(STM32L1XX_HD)|| defined(STM32L1XX_MD_PLUS)
	/* Enable The HSI (16Mhz) */
	RCC_HSICmd(ENABLE);
#endif
#if defined(STM32F30X)
	ADC30x_Configuration();
#endif
}
/*******************************************************************************
* Function Name  : USB_Cable_Config.
* Description    : Software Connection/Disconnection of USB Cable.
* Input          : NewState: new state.
* Output         : None.
* Return         : None
*******************************************************************************/
void USB_Cable_Config(FunctionalState NewState)
{
	if (NewState != DISABLE)
	{
		GPIO_ResetBits(GPIOD, GPIO_Pin_9);
	}
	else
	{
		GPIO_SetBits(GPIOD, GPIO_Pin_9);
	}
}

/*******************************************************************************
* Function Name  : HexToChar.
* Description    : Convert Hex 32Bits value into char.
* Input          : None.
* Output         : None.
* Return         : None.
*******************************************************************************/
static void IntToUnicode(uint32_t value, uint8_t *pbuf, uint8_t len)
{
	uint8_t idx = 0;

	for (idx = 0; idx < len; idx++)
	{
		if (((value >> 28)) < 0xA)
		{
			pbuf[2 * idx] = (value >> 28) + '0';
		}
		else
		{
			pbuf[2 * idx] = (value >> 28) + 'A' - 10;
		}

		value = value << 4;

		pbuf[2 * idx + 1] = 0;
	}
}

/*******************************************************************************
* Function Name  : Get_SerialNum.
* Description    : Create the serial number string descriptor.
* Input          : None.
* Output         : None.
* Return         : None.
*******************************************************************************/
void Get_SerialNum(void)
{
	uint32_t Device_Serial0, Device_Serial1, Device_Serial2;

	Device_Serial0 = *(uint32_t*)ID1;
	Device_Serial1 = *(uint32_t*)ID2;
	Device_Serial2 = *(uint32_t*)ID3;

	Device_Serial0 += Device_Serial2;

	if (Device_Serial0 != 0)
	{
		IntToUnicode(Device_Serial0, &CustomHID_StringSerial[2], 8);
		IntToUnicode(Device_Serial1, &CustomHID_StringSerial[18], 4);
	}
}



/* pin mapping */
/*******************************************************************************
* Function Name  : KeyBoard_Config.
* Description    : Initialization KeyBoard GPIO and LED
* Input          : None.
* Output         : None.
* Return         : None.
*******************************************************************************/
void KeyBoard_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_COLUMN_GPIO, ENABLE);
	for (int i = 0; i < 11; i++)
	{
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
		GPIO_InitStructure.GPIO_Pin = KEYBOARD_COLUMN_GPIO_Pin[i];
		GPIO_Init(KEYBOARD_COLUMN_GPIO_PORT[i], &GPIO_InitStructure);
	}
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ROW_GPIO, ENABLE);
	for (int i = 0; i < 11; i++)
	{
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
		GPIO_InitStructure.GPIO_Pin = KEYBOARD_ROW_GPIO_Pin[i];
		GPIO_Init(KEYBOARD_ROW_GPIO_PORT[i], &GPIO_InitStructure);
	}
}

/*******************************************************************************
* Function Name  : KEYBOARD_GPIO.
* Description    : Initialization KeyBoard GPIO and LED
* Input          : None.
* Output         : None.
* Return         : None.
*******************************************************************************/
uint16_t KEYBOARD_GPIO(uint8_t statues)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	uint16_t bitstatues = 0;
	uint16_t readstatues = 0;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	if (statues == COLUMN_LINE)
	{
		for (int i = 0; i < 11; i++)
		{
			GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
			GPIO_InitStructure.GPIO_Pin = KEYBOARD_COLUMN_GPIO_Pin[i];
			GPIO_Init(KEYBOARD_COLUMN_GPIO_PORT[i], &GPIO_InitStructure);
			GPIO_SetBits(KEYBOARD_COLUMN_GPIO_PORT[i], KEYBOARD_COLUMN_GPIO_Pin[i]);
			GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
			GPIO_InitStructure.GPIO_Pin = KEYBOARD_ROW_GPIO_Pin[i];
			GPIO_Init(KEYBOARD_ROW_GPIO_PORT[i], &GPIO_InitStructure);
			GPIO_ResetBits(KEYBOARD_ROW_GPIO_PORT[i], KEYBOARD_ROW_GPIO_Pin[i]);
		}
		Delay_ms(5);
		for (int i = 0; i < 11; i++)
		{
			bitstatues |= (((uint16_t)(GPIO_ReadInputDataBit(KEYBOARD_COLUMN_GPIO_PORT[i], KEYBOARD_COLUMN_GPIO_Pin[i]))) << i);
		}
		for (int i = 0; i < 11; i++)
		{
			readstatues |= (((uint16_t)(GPIO_ReadInputDataBit(KEYBOARD_COLUMN_GPIO_PORT[i], KEYBOARD_COLUMN_GPIO_Pin[i]))) << i);
		}
	}
	else
	{
		for (int i = 0; i < 11; i++)
		{
			GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
			GPIO_InitStructure.GPIO_Pin = KEYBOARD_COLUMN_GPIO_Pin[i];
			GPIO_Init(KEYBOARD_COLUMN_GPIO_PORT[i], &GPIO_InitStructure);
			GPIO_ResetBits(KEYBOARD_COLUMN_GPIO_PORT[i], KEYBOARD_COLUMN_GPIO_Pin[i]);
			GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
			GPIO_InitStructure.GPIO_Pin = KEYBOARD_ROW_GPIO_Pin[i];
			GPIO_Init(KEYBOARD_ROW_GPIO_PORT[i], &GPIO_InitStructure);
			GPIO_SetBits(KEYBOARD_ROW_GPIO_PORT[i], KEYBOARD_ROW_GPIO_Pin[i]);
		}
		Delay_ms(5);
		for (int i = 0; i < 11; i++)
		{
			bitstatues |= (((uint16_t)(GPIO_ReadInputDataBit(KEYBOARD_ROW_GPIO_PORT[i], KEYBOARD_ROW_GPIO_Pin[i]))) << i);
		}
		for (int i = 0; i < 11; i++)
		{
			readstatues |= (((uint16_t)(GPIO_ReadInputDataBit(KEYBOARD_ROW_GPIO_PORT[i], KEYBOARD_ROW_GPIO_Pin[i]))) << i);
		}
	}
	if (bitstatues != readstatues)readstatues = 0;
	
	return readstatues;
}
/*******************************************************************************
* Function Name  : KeyBoard_Scan.
* Description    : Initialization KeyBoard GPIO and LED
* Input          : None.
* Output         : None.
* Return         : None.
*******************************************************************************/
uint32_t KeyBoard_Scan(void)
{
	//uint32_t statues = 0;
	//statues |= (uint32_t)KEYBOARD_GPIO(COLUMN_LINE) << 16;
	//statues |= (uint32_t)KEYBOARD_GPIO(ROW_LINE);
	/* 07F7 07F7, 07FB 07F7, 07FD 07F7, 07FE 07F7
	   07F7 07FB, 07FB 07FB, 07FD 07FB, 07FE 07FB
	   07F7 07FD, 07FB 07FD, 07FD 07FD, 07FE 07FD
	   07F7 07FE, 07FB 07FE, 07FD 07FE, 07FE 07FEQQ
	*/
	LED0(ON);
	uint32_t keydata = (((uint32_t)(KEYBOARD_GPIO(COLUMN_LINE)) << 16) | ((uint32_t)KEYBOARD_GPIO(ROW_LINE)));
	LED0(OFF);
	USB_KEYBOARD_DATA = 0;
	if (keydata != 0X07FF07FF)
	{
		OLD_KEYDATA = keydata;
		
		switch (keydata)
		{
			/* LEFT KEYBOARD */
		case 0x07BF07EF://0000111101111110000011111101111
			Trace(USART1, "A");
			USB_KEYBOARD_DATA = KeyBoard_A;
			break;
		case 0x07DF07BF://00000111110111110000011110111111
			USB_KEYBOARD_DATA = KeyBoard_B;
			Trace(USART1, "B");
			break;
		case 0x07DF07DF://0000‭0111110111110000011111011111‬
			USB_KEYBOARD_DATA = KeyBoard_C;
			Trace(USART1, "C");
			break;
		case 0x07DF07EF://0000‭0111110111110000011111101111‬
			USB_KEYBOARD_DATA = KeyBoard_D;
			Trace(USART1, "D");
			break;
		case 0x07EF07BF://0000‭0111111011110000011110111111‬
			USB_KEYBOARD_DATA = KeyBoard_E;
			Trace(USART1, "E");
			break;
		case 0x07EF07DF://0000‭0111111011110000011111011111‬
			USB_KEYBOARD_DATA = KeyBoard_F;
			Trace(USART1, "F");
			break;
		case 0x07EF07EF://‭00000111111011110000011111101111‬
			USB_KEYBOARD_DATA = KeyBoard_G;
			Trace(USART1, "G");
			break;
			/* BUTTON KEYBOARD */
		case 0x077F077F://0000‭0111011111110000011101111111‬
			USB_KEYBOARD_DATA = KeyBoard_D1;
			Trace(USART1, "D1");
			break;
		case 0x06FF077F://00000110111111110000011101111111?
			USB_KEYBOARD_DATA = KeyBoard_D2;
			Trace(USART1, "D2");
			break;
		case 0x05FF077F://0000‭0101111111110000011101111111‬
			USB_KEYBOARD_DATA = KeyBoard_D3;
			Trace(USART1, "D3");
			break;
		case 0x077F06FF://0000‭0111011111110000011011111111‬
			USB_KEYBOARD_DATA = KeyBoard_D4;
			Trace(USART1, "D4");
			break;
		case 0x06ff06FF://0000110111111110000011011111111
			USB_KEYBOARD_DATA = KeyBoard_D5;
			Trace(USART1, "D5");
			break;
		case 0x05ff06FF://0000101111111110000011011111111
			USB_KEYBOARD_DATA = KeyBoard_D6;
			Trace(USART1, "D6");
			break;
		case 0x077f05FF://0000111011111110000010111111111
			USB_KEYBOARD_DATA = KeyBoard_D7;
			Trace(USART1, "D7");
			break;
		case 0x06ff05FF://0000110111111110000010111111111
			USB_KEYBOARD_DATA = KeyBoard_D8;
			Trace(USART1, "D8");
			break;
		case 0x05ff05FF://0000101111111110000010111111111
			USB_KEYBOARD_DATA = KeyBoard_D9;
			Trace(USART1, "D9");
			break;
			/* RIGHT KEYBOARD */
		case 0x07fE07FE://0000111111111100000011111111110
			USB_KEYBOARD_DATA = KeyBoard_H;
			Trace(USART1, "H");
			break;
		case 0x07fE07FD://0000111111111100000011111111101
			USB_KEYBOARD_DATA = KeyBoard_I;
			Trace(USART1, "I");
			break;
		case 0x07fE07FB://0000111111111100000011111111011
			USB_KEYBOARD_DATA = KeyBoard_Caps_Lock;//KeyBoard_J
			Trace(USART1, "J");
			break;
		case 0x07FD07FE://0000111111111010000011111111110
			USB_KEYBOARD_DATA = KeyBoard_K;
			Trace(USART1, "K");
			break;
		case 0x07FD07FD://0000111111111010000011111111101
			USB_KEYBOARD_DATA = KeyBoard_L;
			Trace(USART1, "L");
			break;
		case 0x07FD07FB://0000111111111010000011111111011
			USB_KEYBOARD_DATA = KeyBoard_M;
			Trace(USART1, "M");
			break;
		case 0x07FD07F7://0000111111111010000011111110111
			USB_KEYBOARD_DATA = KeyBoard_N;
			Trace(USART1, "N");
			break;

		case 0x07F707FE://0000111111101110000011111111110
			USB_KEYBOARD_DATA = KeyBoard_O;
			Trace(USART1, "O");
			break;
		case 0x07F707FD://0000111111101110000011111111101
			USB_KEYBOARD_DATA = KeyBoard_P;
			Trace(USART1, "P");
			break;
		case 0x07F707FB://0000111111101110000011111111011
			USB_KEYBOARD_DATA = KeyBoard_Q;
			Trace(USART1, "Q");
			break;
		case 0x07F707F7://0000111111101110000011111110111
			USB_KEYBOARD_DATA = KeyBoard_R;
			Trace(USART1, "R");
			break;

		case 0x07FB07FE://0000111111110110000011111111110
			USB_KEYBOARD_DATA = KeyBoard_S;
			Trace(USART1, "S");
			break;
		case 0x07FB07FD://0000111111110110000011111111101
			USB_KEYBOARD_DATA = KeyBoard_T;
			Trace(USART1, "T");
			break;
		case 0x07FB07FB://0000111111110110000011111111011
			USB_KEYBOARD_DATA = KeyBoard_U;
			Trace(USART1, "U");
			break;
		case 0x07FB07F7://0000111111110110000011111110111
			USB_KEYBOARD_DATA = KeyBoard_V;
			Trace(USART1, "V");
			break;
		default:
			break;
		}
		
	}
	while (PrevXferComplete != 1);
	if ((PrevXferComplete) && (bDeviceState == CONFIGURED))
	{
		PrevXferComplete = 0;
		USB_KEYBOARD_DATAS[0] = 0x01;
		USB_KEYBOARD_DATAS[1] = 0x00;//modifier
		USB_KEYBOARD_DATAS[2] = 0x00;//reserved
		USB_KEYBOARD_DATAS[3] = USB_KEYBOARD_DATA;//keycode1
		USB_KEYBOARD_DATAS[4] = 0x00;//keycode2
		USB_KEYBOARD_DATAS[5] = 0x00;//keycode3
		USB_KEYBOARD_DATAS[6] = 0x00;//keycode4
		USB_KEYBOARD_DATAS[7] = 0x00;//keycode5
		USB_KEYBOARD_DATAS[8] = 0x00;//keycode6
		USB_SIL_Write(EP1_IN, (uint8_t*)USB_KEYBOARD_DATAS, 9);
		SetEPTxValid(ENDP1);
	}
	return (keydata);
}
